﻿using System;
using System.Reflection;

namespace DARE
{
    namespace Tools
    {

        public static class Singleton<T> where T : class
        {

        #region fields

            static volatile T m_instance;
            static object m_lock = new object();

        #endregion

            static Singleton()
            {
            }

            public static T Instance
            {
                get
                {
                    if (m_instance == null)
                    {
                        lock (m_lock)
                        {
                            if (m_instance == null)
                            {
                                ConstructorInfo constructor = null;

                                try
                                {
                                    // exclude public constructors
                                    constructor = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0], null);
                                }
                                catch (Exception exception)
                                {
                                    throw new Exception("Singleton exception: " + exception.Message);
                                }
                                // private or protected constructor is missing
                                if ((constructor == null) || constructor.IsAssembly)
                                    throw new Exception(string.Format("Singleton exception: Private or protected constructor is missing for '{0}'.", typeof(T).Name));
                                m_instance = (T)constructor.Invoke(null);
                            }
                        }
                    }
                    return m_instance;
                }
            }
        }
    }
}
